﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CopyFile.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the CopyFile type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Actions.Wss.File
{
    using System;

    using Collaboris.Saf.Actions.Wss.Entities;
    using Collaboris.Saf.Engine;
    using Collaboris.SharePoint.Wss.Files;
    using Collaboris.Utils;

    using Microsoft.SharePoint;

    using SharePoint.Wss.Attributes;

    /// <summary>
    /// This Action is reponsible for moving a collection
    /// of files from list to another.
    /// </summary>
    /// <remarks>
    /// Some Rules :
    /// If 
    ///     - destination file exists 
    ///     - ovewrite is true
    ///     - checked out
    /// the file will be overwritten.
    /// </remarks>
    /// <remarks>
    /// If this is used to copy MOSS Publishing pages, or any library that supports
    /// versioning. The destination file will :
    /// 
    ///     - 
    ///     - .
    ///     - only the latest version of the source file is copied.
    ///     - in order to copy a file to the destination it needs to be checked out first.
    ///       hence, it is advisable that you prefix this action with the "CheckoutAction"
    ///       and then run "PublishPages" afterwards in one macro.
    /// </remarks>
    [CollaborisClass(
        Title = "Copy File",
        ReleaseStatus = ReleaseStatus.Beta,
        DisableDocumentation = false,
        ContactAuthorEmail = "Support@Collaboris.co.uk",
        UndoImplemented = false,
        Summary = "Copies a single file from a source list to a destination list (in SharePoint).",
        Remarks = "If this is used to copy MOSS Publishing pages (or any library that supports versioning and/or approvals), " +
                  @"the following rules apply : <br/><br/><ul><li>The file will be copied into the destination as 'draft'.</li>" +
                  @"<li>If the file already exists in the desination and 'OverwriteInDestination' is 'False', then a new version is created.</li>" +
                  @"<li>If the file already exists in the desination and 'OverwriteInDestination' is 'True', then all versions are deleted.</li>" +
                  @"<li>Only the latest copy of the source file is copied.</li>" +
                  @"<li>To copy the file over a destination file, it needs to be checked out. Hence, it often best to mix this action in a macro " +
                  @"with <a href=""Collaboris.Saf.Actions.Wss.File.CheckInFiles.html"">Check in Files</a>, " +
                  @"<a href=""Collaboris.Saf.Actions.Wss.File.CheckOutFile.html"">Check Out Files</a>, " +
                  @"and optionally, <a href=""Collaboris.Saf.Actions.Wss.File.PublishFiles.html"">Publish Files</a> with " +
                  @"<a href=""Collaboris.Saf.Actions.Wss.File.ApproveFiles.html"">ApproveFiles</a>.</li></ul>",
        ClassGuid = "{156E17A5-A7BA-4e1f-8A48-1BC341A7C647}"
    )
    ]
    public class CopyFile : WSSActionBase<CopyFileInfo>
    {
        #region Fields (1) 

        /// <summary>
        /// Set up the Action Name 
        /// </summary>
        //private const string ActionName = "Collaboris.SharePoint.Actions.Wss.File.CopyFiles";

        #endregion Fields 

        #region Methods (5) 

        /// <summary>
        /// When called moves the files from the originating location
        /// to the target location.
        /// </summary>
        /// <param name="context">
        /// </param>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// </returns>
        protected override ProcessStatus DoAction(SafContext context, CopyFileInfo entity)
        {
            this.Trace.TraceMethodStart("DoAction");

            ValidationHelper.VerifyObjectArgument(context.Site, "context.Site");
            this.ProcessCopyFile(entity, context.Site, ProcessMode.Do);

            this.Trace.TraceMethodEnd("DoAction");

            return ProcessStatus.Success;
        }

        /*
        /// <summary>
        /// Return the name of this Action
        /// </summary>
        /// <returns></returns>
        public override string Name
        {
            get
            {
                return "Collaboris.SharePoint.Actions.Wss.File.CopyFile";
            }
        }
*/

        /// <summary>
        /// When called moves the file back to the
        /// original location.
        /// </summary>
        /// <param name="context">
        /// IContext defining the current context.
        /// </param>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// ProcessStatus signalling to the Macro what its outcome was.
        /// </returns>
        protected override ProcessStatus UndoAction(SafContext context, CopyFileInfo entity)
        {
            //return this.ProcessAction(context, ProcessMode.Undo, entity);
            this.Trace.TraceMethodStart("UndoAction");


            ValidationHelper.VerifyObjectArgument(context.Site, "context.Site");
            // this.ProcessCopyFile(entity, context.Site, ProcessMode.Undo);

            this.Trace.TraceMethodEnd("UndoAction");

            return ProcessStatus.Success;

        }

        /// <summary>
        /// Copy Files as defined in the CopyFileInfoCollection collection.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="site">
        /// The site.
        /// </param>
        /// <param name="mode">
        /// The mode.
        /// </param>
        private void ProcessCopyFile(CopyFileInfo entity, SPSite site, ProcessMode mode)
        {
            this.Trace.TraceMethodStart("DoCopyFile");

            string srcUrl = string.Empty;
            string desUrl = string.Empty;
            bool overwrite = false;

            if (mode == ProcessMode.Do)
            {
                srcUrl = entity.SourceFileUrl;
                desUrl = entity.DestinationFileUrl;
                overwrite = entity.OverwriteInDestination.Value;                                    
            }
            else 
            {
                // If we are undoing, then

                // this is the case if we deleted it
                if (entity.OverwriteInSource.Value == true)
                {
                    desUrl = entity.SourceFileUrl;
                    srcUrl = entity.DestinationFileUrl;
                    // this is the only slightly risky bit
                    // as another process may have overwritten
                    overwrite = entity.OverwriteInSource.Value;
                }
            }                               

            try
            {
                // Verify
                
                ValidationHelper.VerifyStringArgument(srcUrl, "srcUrl");
                ValidationHelper.VerifyStringArgument(desUrl, "desUrl");

                this.Trace.TraceVerbose("Coping '{0}' to '{1}'", srcUrl, desUrl);

                // Now lets attempt the copy
                SPFileHelper.CopyFile(srcUrl, desUrl, overwrite, entity.DeleteInSource.Value);
            }
            catch (Exception ex)
            {
                this.Trace.TraceException("DoCopyFile", ex);
                // Do not barf as we dont want to stop just
                // because we hit one file that cant copy.
            }

            this.Trace.TraceMethodEnd("DoCopyFile");           
        }

        protected override bool IsValid(SafContext context, CopyFileInfo entity, ref System.Collections.Generic.List<ValidationError> errors, ProcessMode mode)
        {
            int currentCount = errors.Count;

            // Validate each object now.
            ValidateStringForNull(entity.DestinationFileUrl, "CopyFileInfo.DestinationFileUrl", ref errors);
            ValidateStringForNull(entity.SourceFileUrl, "CopyFileInfo.SourceFileUrl", ref errors);
            ValidateNullable(entity.DeleteInSource, "CopyFileInfo.DeleteInSource", ref errors);
            ValidateNullable(entity.OverwriteInSource, "CopyFileInfo.OverwriteInSource", ref errors);

            // Have we added errors ?
            return errors.Count == currentCount;
        }

        /*
        /// <summary>
        /// Process the Action for either Do or Undo
        /// </summary>
        /// <param name="context">
        /// </param>
        /// <param name="mode">
        /// </param>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// </returns>
        private ProcessStatus ProcessAction(SafContext context, ProcessMode mode, CopyFileInfo entity)
        {
            // Do some Initial Tracing
            DoTracing(this.Name, mode, entity);

            // Attempt to get the Action context
            //Library.Engine.SafContext ctx = GetContext(context);

            // get the current Web
            SPSite currentSite = context.Site;

            ValidationHelper.VerifyObjectArgument(currentSite, "currentSite");

            this.Trace.TraceVerbose("{0}Action(): Copying Files.", mode);

            this.DoCopyFile(entity, currentSite, mode);

            this.Trace.TraceInfo(string.Format("{0}Action(): Ending.", mode));

            return ProcessStatus.Success;
        }
        */
		
        #endregion Methods 
    }
}